//////////////////////////////////////////////////////////////////////////////////////////////////////////
//		            BulletHingeConstraint
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma warning (disable: 4819)
#include "CKAll.h"
#include "BulletManager.h"

#define INPUT_PARAMENTER_OBJ_A					0
#define INPUT_PARAMENTER_OBJ_B					1
#define INPUT_PARAMENTER_PIVOT_A				2
#define INPUT_PARAMENTER_AXIS_A					3
#define INPUT_PARAMENTER_PIVOT_B					4
#define INPUT_PARAMENTER_AXIS_B					5
#define INPUT_PARAMENTER_REF_A					6
#define INPUT_PARAMENTER_DISABLE_COLLISION_AandB	7
#define INPUT_PARAMENTER_LOWERLIMIT			8
#define INPUT_PARAMENTER_UPPERLIMIT			9
#define INPUT_PARAMENTER_SOFTNESS				10
#define INPUT_PARAMENTER_BIASFACTOR			11

CKObjectDeclaration	*FillBehaviorBulletHingeConstraintDecl();
CKERROR CreateBulletHingeConstraintProto(CKBehaviorPrototype **);
int BulletHingeConstraint(const CKBehaviorContext& BehContext);
//[!output BB_CALLBACKDECL]

CKObjectDeclaration	*FillBehaviorBulletHingeConstraintDecl()
{
	CKObjectDeclaration *od = CreateCKObjectDeclaration("BulletHingeConstraint");	
	
	od->SetType(CKDLL_BEHAVIORPROTOTYPE);
	od->SetVersion(0x00000001);
	od->SetCreationFunction(CreateBulletHingeConstraintProto);
	od->SetDescription("Bullet Hinge Constraint");
	od->SetCategory("Bullet/Constraint");
	od->SetGuid(CKGUID(0x3c804b94,0x72096678));
	od->SetAuthorGuid(CKGUID(0x457d2f46,0x3ee809a8));
	od->SetAuthorName("gjfeilipu");
	od->SetCompatibleClassId(CKCID_BEOBJECT);

	return od;
}

CKERROR CreateBulletHingeConstraintProto(CKBehaviorPrototype** pproto)
{
	CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("BulletHingeConstraint");
	if (!proto) {
		return CKERR_OUTOFMEMORY;
	}

//[!output INPUT_DECL]
//[!output OUTPUT_DECL]
//[!output INPUTP_DECL]
//[!output OUTPUTP_DECL]
	proto->DeclareInput("In");
	proto->DeclareOutput("Out");

	proto->DeclareInParameter("Object_A",CKPGUID_3DENTITY);
	proto->DeclareInParameter("Object_B",CKPGUID_3DENTITY);
	proto->DeclareInParameter("Pivot_A",CKPGUID_VECTOR,"0,0,0");
	proto->DeclareInParameter("Axis_A",CKPGUID_VECTOR,"0,1,0");
	proto->DeclareInParameter("Pivot_B",CKPGUID_VECTOR,"0,0,0");
	proto->DeclareInParameter("Axis_B",CKPGUID_VECTOR,"0,1,0");
	proto->DeclareInParameter("ReferenceFrameA",CKPGUID_BOOL);
	proto->DeclareInParameter("DisableCollisionAandB",CKPGUID_BOOL);
	proto->DeclareInParameter("LowerLimit",CKPGUID_FLOAT,"0");
	proto->DeclareInParameter("UpperLimit",CKPGUID_FLOAT,"0");
	proto->DeclareInParameter("Softness",CKPGUID_FLOAT,"0.9");
	proto->DeclareInParameter("BiasFactor",CKPGUID_FLOAT,"0.3");

	proto->DeclareOutParameter("Constraint ID",CKPGUID_INT,"-1");

//----	Local Parameters Declaration

//----	Settings Declaration
//[!output BB_FLAGS]
//[!output BB_CALLBACKREG]
	proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
	proto->SetFunction(BulletHingeConstraint);

	*pproto = proto;
	return CK_OK;
}

int BulletHingeConstraint(const CKBehaviorContext& BehContext)
{
	CKBehavior* beh = BehContext.Behavior;
	CKContext* cex = beh->GetCKContext();
	beh->ActivateInput(0,FALSE);
	beh->ActivateOutput(0,TRUE);
	
	BulletManager* bManager = (BulletManager*)cex->GetManagerByGuid(BulletManagerGUID);//->addRigidBody(btRigidBody *body);
	if(bManager)
	{
		btVector3 btPivotA, btPivotB, btAxisA, btAxisB;
		VxVector vtPivotA, vtPivotB, vtAxisA, vtAxisB;
		bool referenceFrameA;
		bool disableCollisionAandB;
		btScalar btLowerLimit, btUpperLimit;
		float softness = 0;
		float biasFactor = 0;

		beh->GetInputParameterValue(INPUT_PARAMENTER_REF_A, &referenceFrameA);
		beh->GetInputParameterValue(INPUT_PARAMENTER_DISABLE_COLLISION_AandB, &disableCollisionAandB);
		beh->GetInputParameterValue(INPUT_PARAMENTER_LOWERLIMIT, &btLowerLimit);
		beh->GetInputParameterValue(INPUT_PARAMENTER_UPPERLIMIT, &btUpperLimit);
		beh->GetInputParameterValue(INPUT_PARAMENTER_SOFTNESS, &softness);
		beh->GetInputParameterValue(INPUT_PARAMENTER_BIASFACTOR, &biasFactor);

		beh->GetInputParameterValue(INPUT_PARAMENTER_PIVOT_A, &vtPivotA);
		beh->GetInputParameterValue(INPUT_PARAMENTER_AXIS_A, &vtAxisA);
		beh->GetInputParameterValue(INPUT_PARAMENTER_PIVOT_B, &vtPivotB);
		beh->GetInputParameterValue(INPUT_PARAMENTER_AXIS_B, &vtAxisB);

		
		btPivotA.setValue(vtPivotA.x, vtPivotA.y, -vtPivotA.z);
		btAxisA.setValue(vtAxisA.x, vtAxisA.y, -vtAxisA.z);
		btPivotB.setValue(vtPivotB.x, vtPivotB.y, -vtPivotB.z);
		btAxisB.setValue(vtAxisB.x, vtAxisB.y, -vtAxisB.z);

		//if(NULL !=body)
		{		
			CK3dEntity* obj_A = (CK3dEntity*)beh->GetInputParameterObject(INPUT_PARAMENTER_OBJ_A);
			CK3dEntity* obj_B = (CK3dEntity*)beh->GetInputParameterObject(INPUT_PARAMENTER_OBJ_B);
			btRigidBody* body_A =  bManager->findRigidBody(obj_A);
			btRigidBody* body_B =  bManager->findRigidBody(obj_B);
			int ID = -1;
			ID = bManager->addHingeConstraint(body_A,body_B, 
				btPivotA, btPivotB, btAxisA, btAxisA,
				referenceFrameA, disableCollisionAandB, 
				btLowerLimit, btUpperLimit, softness, biasFactor);
			beh->SetOutputParameterValue(0, &ID);
		}
	}
	return CKBR_OK;
}